home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / midas060 / src / midasfx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-16  |  17.8 KB  |  655 lines

  1. /*      midasfx.c
  2.  *
  3.  * MIDAS sound effect library
  4.  *
  5.  * $Id: midasfx.c,v 1.4 1997/01/16 18:41:59 pekangas Exp $
  6.  *
  7.  * Copyright 1996,1997 Housemarque Inc.
  8.  *
  9.  * This file is part of the MIDAS Sound System, and may only be
  10.  * used, modified and distributed under the terms of the MIDAS
  11.  * Sound System license, LICENSE.TXT. By continuing to use,
  12.  * modify or distribute this file you indicate that you have
  13.  * read the license and understand and accept it fully.
  14. */
  15.  
  16.  
  17. #include "lang.h"
  18. #include "mtypes.h"
  19. #include "errors.h"
  20. #include "mmem.h"
  21. #include "sdevice.h"
  22. #include "midasfx.h"
  23. #include "file.h"
  24.  
  25.  
  26. /* Magic constant that is used to identify playing handles that refer to
  27.    sounds on automatic effect channels: */
  28. #define AUTOMAGIC 0x100
  29.  
  30. /* Maximum playing handle: */
  31. #define MAXHANDLE 0xFFFE
  32.  
  33. /* Magic channel number - not found: */
  34. #define NOCHANNEL 0xFFFF
  35.  
  36.  
  37.  
  38. /****************************************************************************\
  39. *       enum fxFunctIDs
  40. *       ---------------
  41. * Description:  Function IDs for sound effect library functions
  42. \****************************************************************************/
  43.  
  44. enum fxFunctIDs
  45. {
  46.     ID_fxInit = ID_fx,
  47.     ID_fxClose,
  48.     ID_fxLoadRawSample,
  49.     ID_fxFreeSample,
  50.     ID_fxSetAutoChannels,
  51.     ID_fxPlaySample,
  52.     ID_fxStopSample,
  53.     ID_fxSetSampleRate,
  54.     ID_fxSetSampleVolume,
  55.     ID_fxSetSamplePanning,
  56.     ID_fxSetSamplePriority
  57. };
  58.  
  59.  
  60.  
  61. static unsigned numAutoChannels;        /* Number of auto FX channels */
  62. static fxChannel *autoChannels;         /* Automatic effect channels */
  63. static unsigned nextHandle;             /* Next sample playing handle */
  64. static SoundDevice *SD;                 /* Sound Device for the effects */
  65. static unsigned nextChannel;            /* Next automatic channel */
  66.  
  67.  
  68.  
  69. /****************************************************************************\
  70. *
  71. * Function:     int fxInit(void)
  72. *
  73. * Description:  Initializes the sound effect library
  74. *
  75. * Input:        SoundDevice *SD         Pointer to the Sound Device that will
  76. *                                       be used for playing the effects
  77. *
  78. * Returns:      MIDAS error code
  79. *
  80. \****************************************************************************/
  81.  
  82. int CALLING fxInit(SoundDevice *_SD)
  83. {
  84.     /* Remember the Sound Device: */
  85.     SD = _SD;
  86.  
  87.     /* We don't have any automatic channels: */
  88.     numAutoChannels = 0;
  89.     autoChannels = NULL;
  90.  
  91.     nextHandle = AUTOMAGIC;
  92.     nextChannel = 0;
  93.  
  94.     return OK;
  95. }
  96.  
  97.  
  98.  
  99.  
  100. /****************************************************************************\
  101. *
  102. * Function:     int fxClose(void)
  103. *
  104. * Description:  Uninitializes the sound effect library
  105. *
  106. * Returns:      MIDAS error code
  107. *
  108. \****************************************************************************/
  109.  
  110. int CALLING fxClose(void)
  111. {
  112.     int         error;
  113.     unsigned    i;
  114.     unsigned    chan;
  115.  
  116.     /* Check if we have automatic effect channels. If yes, clear the sounds
  117.        on them and free the channel structures: */
  118.     if ( numAutoChannels != 0 )
  119.     {
  120.         for ( i = 0; i < numAutoChannels; i++ )
  121.         {
  122.             chan = autoChannels[i].sdChannel;
  123.  
  124.             if ( (error = SD->StopSound(chan)) != OK )
  125.                 PASSERROR(ID_fxClose);
  126.         }
  127.  
  128.         if ( (error = memFree(autoChannels)) != OK )
  129.             PASSERROR(ID_fxClose);
  130.     }
  131.  
  132.     return OK;
  133. }
  134.  
  135.  
  136.  
  137.  
  138. /****************************************************************************\
  139. *
  140. * Function:     int fxLoadRawSample(char *fileName, unsigned sampleType,
  141. *                   int loopSample, unsigned *sampleHandle)
  142. *
  143. * Description:  Loads a raw sample file into memory and adds the sample to
  144. *               the sound device.
  145. *
  146. * Input:        char *fileName          sample file name
  147. *               unsigned sampleType     sample type, see enum sdSampleType
  148. *               int loopSample          1 if sample is looped, 0 if not
  149. *               unsigned *sampleHandle  pointer to sample handle variable
  150. *
  151. * Returns:      MIDAS error code. The sample handle for the sample will be
  152. *               written to *sampleHandle.
  153. *
  154. \****************************************************************************/
  155.  
  156. int CALLING fxLoadRawSample(char *fileName, unsigned sampleType,
  157.     int loopSample, unsigned *sampleHandle)
  158. {
  159.     int         error;
  160.     static char *buffer;
  161.     static fileHandle f;
  162.     static long len;
  163.     static sdSample smp;
  164.  
  165.  
  166.     /* Open the sound effect file: */
  167.     if ( (error = fileOpen(fileName, fileOpenRead, &f)) != OK )
  168.         PASSERROR(ID_fxLoadRawSample);
  169.  
  170.     /* Get file size: */
  171.     if ( (error = fileGetSize(f, &len)) != OK )
  172.     {
  173.         fileClose(f);
  174.         PASSERROR(ID_fxLoadRawSample);
  175.     }
  176.  
  177.     /* Allocate sample loading buffer: */
  178.     if ( (error = memAlloc(len, (void**) &buffer)) != OK )
  179.     {
  180.         fileClose(f);
  181.         PASSERROR(ID_fxLoadRawSample);
  182.     }
  183.  
  184.     /* Read the sample: */
  185.     if ( (error = fileRead(f, buffer, len)) != OK )
  186.     {
  187.         fileClose(f);
  188.         memFree(buffer);
  189.         PASSERROR(ID_fxLoadRawSample);
  190.     }
  191.  
  192.     /* Close the sample file: */
  193.     if ( (error = fileClose(f)) != OK )
  194.     {
  195.         memFree(buffer);
  196.         PASSERROR(ID_fxLoadRawSample);
  197.     }
  198.  
  199.     /* Build Sound Device sample structure for the sample: */
  200.     smp.sample = buffer;
  201.     smp.samplePos = sdSmpConv;
  202.     smp.sampleType = sampleType;
  203.     smp.sampleLength = len;
  204.  
  205.     if ( loopSample )
  206.     {
  207.         /* Loop the whole sample: */
  208.         smp.loopMode = sdLoop1;
  209.         smp.loop1Start = 0;
  210.         smp.loop1End = len;
  211.         smp.loop1Type = loopUnidir;
  212.     }
  213.     else
  214.     {
  215.         /* No loop: */
  216.         smp.loopMode = sdLoopNone;
  217.         smp.loop1Start = smp.loop1End = 0;
  218.         smp.loop1Type = loopNone;
  219.     }
  220.  
  221.     /* No loop 2: */
  222.     smp.loop2Start = smp.loop2End = 0;
  223.     smp.loop2Type = loopNone;
  224.  
  225.     /* Add the sample to the Sound Device: */
  226.     if ( (error = SD->AddSample(&smp, 1, sampleHandle)) != OK )
  227.     {
  228.         memFree(buffer);
  229.         PASSERROR(ID_fxLoadRawSample);
  230.     }
  231.  
  232.     /* Deallocate the buffer: */
  233.     if ( (error = memFree(buffer)) != OK )
  234.         PASSERROR(ID_fxLoadRawSample);
  235.  
  236.     return OK;
  237. }
  238.  
  239.  
  240.  
  241.  
  242. /****************************************************************************\
  243. *
  244. * Function:     int fxFreeSample(unsigned sample)
  245. *
  246. * Description:  Deallocates a sample and frees it from the Sound Device.
  247. *
  248. * Input:        unsigned sample         sample handle for the sample to be
  249. *                                       deallocated.
  250. *
  251. * Returns:      MIDAS error code
  252. *
  253. \****************************************************************************/
  254.  
  255. int CALLING fxFreeSample(unsigned sample)
  256. {
  257.     int         error;
  258.  
  259.     /* Just free the sample from the Sound Device: */
  260.     if ( (error = SD->RemoveSample(sample)) != OK )
  261.         PASSERROR(ID_fxFreeSample);
  262.  
  263.     return OK;
  264. }
  265.  
  266.  
  267.  
  268.  
  269. /****************************************************************************\
  270. *
  271. * Function:     int fxSetAutoChannels(int numChannels,
  272. *                   unsigned *channelNumbers)
  273. *
  274. * Description:  Sets the channel numbers that can be used as automatic effect
  275. *               channels.
  276. *
  277. * Input:        int numChannels             number of channels that can be
  278. *                                           used
  279. *               unsigned *channelNumbers    pointer to a table that contains
  280. *                                           the channels that can be used
  281. *
  282. * Returns:      MIDAS error code
  283. *
  284. \****************************************************************************/
  285.  
  286. int CALLING fxSetAutoChannels(int numChannels, unsigned *channelNumbers)
  287. {
  288.     int         error;
  289.     unsigned    i;
  290.     unsigned    chan;
  291.     fxChannel   *fxchan;
  292.  
  293.     /* Check if there are previous automatic effect channels. If yes, clear
  294.        them and free the channel structures: */
  295.     if ( numAutoChannels != 0 )
  296.     {
  297.         for ( i = 0; i < numAutoChannels; i++ )
  298.         {
  299.             chan = autoChannels[i].sdChannel;
  300.  
  301.             if ( (error = SD->StopSound(chan)) != OK )
  302.                 PASSERROR(ID_fxClose);
  303.         }
  304.  
  305.         if ( (error = memFree(autoChannels)) != OK )
  306.             PASSERROR(ID_fxClose);
  307.     }
  308.  
  309.     if ( numChannels )
  310.     {
  311.         /* Allocate memory for channel structures: */
  312.         numAutoChannels = numChannels;
  313.         if ( (error = memAlloc(numChannels * sizeof(fxChannel),
  314.             (void**) &autoChannels)) != OK )
  315.             PASSERROR(ID_fxSetAutoChannels);
  316.  
  317.         /* Initialize channels: */
  318.         for ( i = 0; i < (unsigned) numChannels; i++ )
  319.         {
  320.             fxchan = &autoChannels[i];
  321.             fxchan->sdChannel = channelNumbers[i];
  322.             fxchan->sampleHandle = 0;
  323.             fxchan->playHandle = 0;
  324.             fxchan->priority = 0;
  325.         }
  326.     }
  327.     else
  328.     {
  329.         /* There are no automatic effect channels: */
  330.         numAutoChannels = 0;
  331.         autoChannels = NULL;
  332.     }
  333.  
  334.     nextHandle = AUTOMAGIC;
  335.     nextChannel = 0;
  336.  
  337.     return OK;
  338. }
  339.  
  340.  
  341.  
  342.  
  343. /****************************************************************************\
  344. *
  345. * Function:     int fxPlaySample(unsigned channel, unsigned sample,
  346. *                   int priority, unsigned rate, unsigned volume, int panning,
  347. *                   unsigned *playHandle)
  348. *
  349. * Description:  Starts playing a sound effect sample on a channel
  350. *
  351. * Input:        unsigned channel        channel number, or fxAutoChannel for
  352. *                                       automatic selection
  353. *               unsigned sample         sample handle
  354. *               int priority            effect priority, the higher the value
  355. *                                       the higher the priority
  356. *               unsigned rate           effect initial sample rate
  357. *               unsigned volume         effect initial volume (0-64)
  358. *               int panning             effect initial panning, see enum
  359. *                                       sdPanning
  360. *               unsigned *playHandle    effect playing handle variable
  361. *
  362. * Returns:      MIDAS error code. The playing handle for the effect will be
  363. *               written to *playHandle.
  364. *
  365. \****************************************************************************/
  366.  
  367. int CALLING fxPlaySample(unsigned channel, unsigned sample, int priority,
  368.     unsigned rate, unsigned volume, int panning, unsigned *playHandle)
  369. {
  370.     int         error;
  371.     unsigned    chan;
  372.     unsigned    handle;
  373.  
  374.     if ( channel == fxAutoChannel )
  375.     {
  376.         /* We should select the channel automatically */
  377.  
  378.         /* Check that we do have automatic channels: */
  379.         if ( numAutoChannels == 0 )
  380.         {
  381.             ERROR(errNoChannels, ID_fxPlaySample);
  382.             return errNoChannels;
  383.         }
  384.  
  385.         handle = nextHandle;
  386.  
  387.         /* We'll just use the next automatic channel: */
  388.         autoChannels[nextChannel].sampleHandle = sample;
  389.         autoChannels[nextChannel].priority = priority;
  390.         autoChannels[nextChannel].playHandle = handle;
  391.         chan = autoChannels[nextChannel].sdChannel;
  392.  
  393.         /* Go to the next channel: */
  394.         nextChannel++;
  395.         if ( nextChannel >= numAutoChannels )
  396.             nextChannel = 0;
  397.  
  398.         /* Prepare next possible play handle: */
  399.         nextHandle++;
  400.         if ( (nextHandle < AUTOMAGIC) || (nextHandle > MAXHANDLE) )
  401.             nextHandle = AUTOMAGIC;
  402.     }
  403.     else
  404.     {
  405.         /* Just use the channel given: */
  406.         chan = channel;
  407.         handle = chan;
  408.     }
  409.  
  410.     /* The handle returned will be >= AUTOMAGIC if it refers to a sound on an
  411.        automagic channel, otherwise it is simply the SD channel number */
  412.  
  413.     /* Stop any previous sound on the channel: */
  414.     if ( (error = SD->StopSound(chan)) != OK )
  415.         PASSERROR(ID_fxPlaySample);
  416.  
  417.     /* Set the sample to the channel: */
  418.     if ( (error = SD->SetSample(chan, sample)) != OK )
  419.         PASSERROR(ID_fxPlaySample);
  420.  
  421.     /* Set the new volume to the channel: */
  422.     if ( (error = SD->SetVolume(chan, volume)) != OK )
  423.         PASSERROR(ID_fxPlaySample);
  424.  
  425.     /* Set the new panning position: */
  426.     if ( (error = SD->SetPanning(chan, panning)) != OK )
  427.         PASSERROR(ID_fxPlaySample);
  428.  
  429.     /* Play the sound: */
  430.     if ( (error = SD->PlaySound(chan, rate)) != OK )
  431.         PASSERROR(ID_fxPlaySample);
  432.  
  433.     *playHandle = handle;
  434.  
  435.     return OK;
  436. }
  437.  
  438.  
  439.  
  440. /****************************************************************************\
  441. *
  442. * Function:     unsigned FindChannel(unsigned playHandle)
  443. *
  444. * Description:  Finds the channel where a sound is being played
  445. *
  446. * Input:        unsigned playHandle     playing handle for the sound
  447. *
  448. * Returns:      Sound Device channel number for the sound, or NOCHANNEL if it
  449. *               is not being played.
  450. *
  451. \****************************************************************************/
  452.  
  453. static unsigned FindChannel(unsigned playHandle)
  454. {
  455.     unsigned    i;
  456.  
  457.     if ( playHandle < AUTOMAGIC )
  458.     {
  459.         /* Just a simple channel number: */
  460.         return playHandle;
  461.     }
  462.  
  463.     /* Search through the channels and try to find the sound: */
  464.     for ( i = 0; i < numAutoChannels; i++ )
  465.     {
  466.         if ( autoChannels[i].playHandle == playHandle )
  467.             return autoChannels[i].sdChannel;
  468.     }
  469.  
  470.     /* We couldn't find it: */
  471.     return NOCHANNEL;
  472. }
  473.  
  474.  
  475.  
  476. /****************************************************************************\
  477. *
  478. * Function:     int fxStopSample(unsigned playHandle)
  479. *
  480. * Description:  Stops playing a sample
  481. *
  482. * Input:        unsigned playHandle     sample playing handle (from
  483. *                                       fxPlaySample)
  484. *
  485. * Returns:      MIDAS error code
  486. *
  487. \****************************************************************************/
  488.  
  489. int CALLING fxStopSample(unsigned playHandle)
  490. {
  491.     unsigned    chan;
  492.     int         error;
  493.  
  494.     /* Find the channel number for the sound, exit if it's not being played:*/
  495.     if ( (chan = FindChannel(playHandle)) == NOCHANNEL )
  496.         return OK;
  497.  
  498.     /* Stop the sound: */
  499.     if ( (error = SD->StopSound(chan)) != OK )
  500.         PASSERROR(ID_fxStopSample);
  501.  
  502.     return OK;
  503. }
  504.  
  505.  
  506.  
  507. /****************************************************************************\
  508. *
  509. * Function:     int fxSetSampleRate(unsigned playHandle, ulong rate)
  510. *
  511. * Description:  Changes the sample rate for a sample that is being played
  512. *
  513. * Input:        unsigned playHandle     sample playing handle (from
  514. *                                       fxPlaySample)
  515. *               ulong rate              new rate
  516. *
  517. * Returns:      MIDAS error code
  518. *
  519. \****************************************************************************/
  520.  
  521. int CALLING fxSetSampleRate(unsigned playHandle, ulong rate)
  522. {
  523.     unsigned    chan;
  524.     int         error;
  525.  
  526.     /* Find the channel number for the sound, exit if it's not being played:*/
  527.     if ( (chan = FindChannel(playHandle)) == NOCHANNEL )
  528.         return OK;
  529.  
  530.     /* Set the new sample rate: */
  531.     if ( (error = SD->SetRate(chan, rate)) != OK )
  532.         PASSERROR(ID_fxSetSampleRate);
  533.  
  534.     return OK;
  535. }
  536.  
  537.  
  538.  
  539.  
  540. /****************************************************************************\
  541. *
  542. * Function:     int fxSetSampleVolume(unsigned playHandle, unsigned volume)
  543. *
  544. * Description:  Changes the volume for a sample that is being played
  545. *
  546. * Input:        unsigned playHandle     sample playing handle (from
  547. *                                       fxPlaySample)
  548. *               unsigned volume         new volume
  549. *
  550. * Returns:      MIDAS error code
  551. *
  552. \****************************************************************************/
  553.  
  554. int CALLING fxSetSampleVolume(unsigned playHandle, unsigned volume)
  555. {
  556.     unsigned    chan;
  557.     int         error;
  558.  
  559.     /* Find the channel number for the sound, exit if it's not being played:*/
  560.     if ( (chan = FindChannel(playHandle)) == NOCHANNEL )
  561.         return OK;
  562.  
  563.     /* Set the new sample rate: */
  564.     if ( (error = SD->SetVolume(chan, volume)) != OK )
  565.         PASSERROR(ID_fxSetSampleVolume);
  566.  
  567.     return OK;
  568. }
  569.  
  570.  
  571.  
  572.  
  573. /****************************************************************************\
  574. *
  575. * Function:     int fxSetSamplePanning(unsigned playHandle, int panning)
  576. *
  577. * Description:  Changes the panning position for a sample that is being played
  578. *
  579. * Input:        unsigned playHandle     sample playing handle (from
  580. *                                       fxPlaySample)
  581. *               int panning             new panning position
  582. *
  583. * Returns:      MIDAS error code
  584. *
  585. \****************************************************************************/
  586.  
  587. int CALLING fxSetSamplePanning(unsigned playHandle, int panning)
  588. {
  589.     unsigned    chan;
  590.     int         error;
  591.  
  592.     /* Find the channel number for the sound, exit if it's not being played:*/
  593.     if ( (chan = FindChannel(playHandle)) == NOCHANNEL )
  594.         return OK;
  595.  
  596.     /* Set the new sample rate: */
  597.     if ( (error = SD->SetPanning(chan, panning)) != OK )
  598.         PASSERROR(ID_fxSetSamplePanning);
  599.  
  600.     return OK;
  601. }
  602.  
  603.  
  604.  
  605.  
  606. /****************************************************************************\
  607. *
  608. * Function:     int fxSetSamplePriority(unsigned playHandle, int priority)
  609. *
  610. * Description:  Changes the priority for a sample that is being played
  611. *
  612. * Input:        unsigned playHandle     sample playing handle (from
  613. *                                       fxPlaySample)
  614. *               int priority            new playing priority
  615. *
  616. * Returns:      MIDAS error code
  617. *
  618. \****************************************************************************/
  619.  
  620. int CALLING fxSetSamplePriority(unsigned playHandle, int priority)
  621. {
  622.     unsigned    i;
  623.  
  624.     /* Check that the handle is for an automatic channel - priorities don't
  625.        make sense otherwise: */
  626.     if ( playHandle < AUTOMAGIC )
  627.         return OK;
  628.  
  629.     /* Try to find the channel the sound is being played on, and set its
  630.        priority if found: */
  631.     for ( i = 0; i < numAutoChannels; i++ )
  632.     {
  633.         if ( autoChannels[i].playHandle == playHandle )
  634.             autoChannels[i].priority = priority;
  635.     }
  636.  
  637.     return OK;
  638. }
  639.  
  640.  
  641. /*
  642.  * $Log: midasfx.c,v $
  643.  * Revision 1.4  1997/01/16 18:41:59  pekangas
  644.  * Changed copyright messages to Housemarque
  645.  *
  646.  * Revision 1.3  1996/09/28 08:12:40  jpaana
  647.  * Fixed for Linux
  648.  *
  649.  * Revision 1.2  1996/09/25 18:36:41  pekangas
  650.  * Fixed to compile in DOS without warnings
  651.  *
  652.  * Revision 1.1  1996/09/22 23:17:48  pekangas
  653.  * Initial revision
  654.  *
  655. */